package cn.buk.tms.dao;

import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.common.sc.Page;
import cn.buk.tms.entity.misc.Product;
import cn.buk.tms.entity.misc.TieInProduct;
import cn.buk.common.util.DateUtil;
import java.util.ArrayList;
import java.util.List;

import jakarta.persistence.criteria.*;
import jakarta.transaction.Transactional;

import cn.buk.tms.entity.misc.TieInProduct_;
import org.springframework.stereotype.Component;

/**
 * Created with IntelliJ IDEA.
 * User: yfdai
 * Date: 14-4-17
 * Time: 下午11:04
 * To change this template use File | Settings | File Templates.
 * @author yfdai
 */
@Component
@Transactional
public class ProductDaoImpl extends AbstractDao implements ProductDao {
    @Override
    public int create(Product product) {
        int retCode = 0;
        em.persist(product);
        em.flush();

        retCode = product.getId();

        return retCode;
    }

    @Override
    public List<Product> findAll() {
        List<Product> products = em.createQuery("select o from Product o order by o.id", Product.class)
                .getResultList();

        return products == null ? new ArrayList<Product>() : products;
    }

    @Override
    public Product getById(int id) {
        return em.find(Product.class, id);
    }

    @Override
    public Product getByCode(String code) {
        List<Product> products = em.createQuery("select o from Product o where o.productCode = :productCode", Product.class)
                .setParameter("productCode", code)
                .getResultList();

        Product product = products.size() > 0 ? products.get(0) : null;

        return product;
    }

    @Override
    public int createTieInProduct(TieInProduct p) {
        if (p.getId() > 0) {
          p.setLastUpdate(DateUtil.getCurDateTime());
        }

        if (p.getId() == 0) {
          em.persist(p);
        } else {
          em.merge(p);
        }
        return 1;
    }

    @Override
    public List<TieInProduct> getAllTieInProducts(int enterpriseId) {
        return em.createQuery("select o from TieInProduct o " +
                "where o.enterpriseId = :enterpriseId  order by o.productCode", TieInProduct.class)
                .setParameter("enterpriseId", enterpriseId)
                .getResultList();
    }

    private List<Predicate> buildPredicates_searchTieInProducts(CriteriaBuilder cb, Root<TieInProduct> root,
                                                                int enterpriseId, CommonSearchCriteria sc) {
        List<Predicate> predicates = new ArrayList<>();
        Predicate where = cb.conjunction();
        predicates.add(where);

        where = cb.equal(root.get(TieInProduct_.enterpriseId), enterpriseId);
        predicates.add(where);

        if (sc.getStatus() > -1) {
            where = cb.equal(root.get(TieInProduct_.status), sc.getStatus());
            predicates.add(where);
        }

        if (sc.getType() > -1) {
            where = cb.equal(root.get(TieInProduct_.productType), sc.getType());
            predicates.add(where);
        }

        return predicates;
    }

    @Override
    public List<TieInProduct> searchTieInProducts(int enterpriseId, CommonSearchCriteria sc) {
        List<TieInProduct> results = null;

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<TieInProduct> cq = cb.createQuery(TieInProduct.class);
        Root<TieInProduct> root = cq.from(TieInProduct.class);
        root.alias("o");

        var predicates0 = buildPredicates_searchTieInProducts(cb,root, enterpriseId, sc);

        //计算根据条件查询得出的数据总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<TieInProduct> countRoot = countQuery.from(TieInProduct.class);
        countRoot.alias("o");

        var predicates1 = buildPredicates_searchTieInProducts(cb,countRoot, enterpriseId, sc);

        countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
        Long count = em.createQuery(countQuery).getSingleResult();

        if (count.intValue() > 0) {
            cq.where(predicates0.toArray(new Predicate[predicates0.size()]));
            List<Order> orderByes = new ArrayList<>();

            orderByes.add(cb.asc(root.get(TieInProduct_.id)));
            cq.orderBy(orderByes);

            Page page = sc.getPage();
            page.setRowCount(count.intValue());
            int i = (page.getPageNo() - 1) * page.getPageSize();

            if (i < 0) {
                i = 0;
            }

            results = em.createQuery(cq)
                .setFirstResult(i)
                .setMaxResults(page.getPageSize()).getResultList();
        }

        return results == null ? new ArrayList<>() : results;
    }

    @Override
    public int deleteTieInProduct(int enterpriseId, int id) {
        int retCode = 0;
        retCode = em.createQuery("delete from TieInProduct o " +
                "where o.enterpriseId = :enterpriseId  and o.id = :id")
                .setParameter("enterpriseId", enterpriseId)
                .setParameter("id", id)
                .executeUpdate();

        return retCode;
    }

    @Override
    public TieInProduct getTieInProductById(int id) {
        return em.find(TieInProduct.class, id);
    }

    @Override
    public TieInProduct getTieInProductByCode(int enterpriseId, String productCode) {
        List<TieInProduct> list = em.createQuery("select o from TieInProduct o " +
                "where o.enterpriseId = :enterpriseId  and o.productCode = :productCode", TieInProduct.class)
                .setParameter("enterpriseId", enterpriseId)
                .setParameter("productCode", productCode)
                .getResultList();

        return list.size() > 0 ? list.get(0) : null;
    }
}
